﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using ChatGPT.Net;
using ChatGPT.Net.DTO;
using ChatGPT.Net.Enums;
using ChatGPT.Net.Session;
using Microsoft.Extensions.ObjectPool;
using NLog;

namespace ChatGpt_WebApp.ThirdApi;

/// <summary>
/// ChatGpt会话AI
/// </summary>
public class PawanChatGptApi : ChatApiBase
{
    static ChatGpt? chatGpt;

    static Dictionary<int, ChatGptClient> clients = new Dictionary<int, ChatGptClient>();

    readonly Microsoft.Extensions.Logging.ILogger _logger;

    readonly AppSetting.ChatGptConfig chatSetting = AppSetting.Current!.ChatGpt;

    public PawanChatGptApi(ILogger<PawanChatGptApi> logger)
    {
        this._logger = logger;
    }

    public static async Task Init(Dictionary<int, ChatGptClientConfig> configs)
    {
        if (chatGpt != null) return;

        chatGpt = new ChatGpt();
        chatGpt.UseCache = true;
        Console.WriteLine("正在连接到会话服务器...");
        foreach (var config in configs)
        {
            var client = await chatGpt.CreateClient(config.Value);
            clients.Add(config.Key, client);
        }
        await chatGpt.WaitForReady();
        Console.WriteLine("服务器连接成功!");

        var logger = LogManager.GetLogger("chatError");
        foreach (var kv in clients)
        {
            var id = kv.Key;
            var client = kv.Value;
            var tokenState = TokenManager.GetToken(id);
            if (tokenState == null) throw new Exception("无效的TokenID");
            client.OnError = (msg) =>
            {
                msg = msg.Trim();
                logger.Log(NLog.LogLevel.Error, $"TokenId:{id} 回答异常:{msg}");

                if (msg.ToLower().StartsWith("too many requests"))
                {
                    tokenState.Confined = true;
                }
                if (msg.ToLower().Contains("expired"))
                {
                    tokenState.Expired = true;
                }
            };
        }
    }



    /// <summary>
    /// 获取客户端
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    private ChatGptClient? GetClient(int id)
    {
        return clients!.FirstOrDefault(f => f.Key == id).Value;
    }

    /// <summary>
    /// 向AI提问
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="question"></param>
    /// <param name="sessionid"></param>
    /// <returns></returns>
    public override async Task<ChatResult> Ask(string question, string sessionid, int tokenid, int characterId = 0)
    {
        var result = new ChatResult();
        try
        {
            await chatGpt.WaitForReady();

            var character = GetCharacter(characterId);
            var aiDesc = string.Format(this.chatSetting.Character!.Template!, character.AiDesc);
            if (characterId == 0) aiDesc = "";

            question = aiDesc + question;

            var count = 1;
            var client = GetClient(tokenid);
            do
            {                
                result.Content = await client!.Ask(question, sessionid);
                //循环等待回答
                if(string.IsNullOrWhiteSpace(result.Content)) await Task.Delay(1000);
            } while (string.IsNullOrWhiteSpace(result.Content) && ++count < 5);

            if (string.IsNullOrWhiteSpace(result.Content))
            {
                _logger.LogWarning("回答为空" + question.Length);
                result.Status = ChatResultStatus.TimeOut;
                result.Success = false;
                result.Content = "源服务器问答请求有些繁忙，待会儿再试试吧";
                return result;
            }
        }
        catch (Exception e)
        {
            _logger.LogError(e, "提问时出现错误,问题长度" + question.Length);
            result.Exception = e;
            result.Success = false;
            result.Content = "我这边好像出现了一些异常状况";
            return result;
        }

        var tokenState = TokenManager.GetToken(tokenid);
        //如果响应成功则表示Token正常
        if (tokenState != null)
        {
            tokenState.Expired = false;
            tokenState.Confined = false;
        }

        result.Success = true;
        result.Status = ChatResultStatus.Success;

        return result;
    }

    /// <summary>
    /// 清除会话记录
    /// </summary>
    /// <param name="sessionId"></param>
    /// <returns></returns>
    public override async Task ResetConversation(string sessionId, int clientid)
    {
        await GetClient(clientid)!.ResetConversation(sessionId);
    }

}

/// <summary>
/// ChatGpt会话AI 服务扩展
/// </summary>
public static class PawanChatGptApiServiceCollectionExtensions
{
    public static IServiceCollection AddPawanChatGptApi(this IServiceCollection services, Action<PawanChatGptApiOptions> config)
    {
        var options = new PawanChatGptApiOptions();
        config(options);

        PawanChatGptApi.Init(options.GetConfigs()).Wait();

        services.AddSingleton<IChatApi, PawanChatGptApi>();
        return services;
    }

    public class PawanChatGptApiOptions
    {
        private Dictionary<int, ChatGptClientConfig> configs = new Dictionary<int, ChatGptClientConfig>();

        public void AddConfig(int id, Action<ChatGptClientConfig> setting)
        {
            var config = new ChatGptClientConfig();
            setting(config);
            this.configs.Add(id, config);
        }

        public Dictionary<int, ChatGptClientConfig> GetConfigs()
        {
            return configs;
        }
    }
}

